package com.yilin.tms.core.commons.base;

import com.yilin.commons.exception.BusinessException;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.commons.utils.UserUtil;
import com.yilin.tms.core.components.interceptor.ReqProviderInterceptor;
import com.yilin.tms.core.entity.user.account.Account;
import org.apache.commons.lang.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

public abstract class BaseController extends BaseCode {

    private Logger logger = LoggerFactory.getLogger(BaseController.class);
    @Autowired
    protected HttpServletRequest request;


    public Account getLoginUser() {
        return UserUtil.getLoginUser(request);
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                try {
                    if (StringUtils.isBlank(text)) {
                        setValue(null);
                        return;
                    }
                    if (text.contains("T")) text = text.replace("T", " ");
                    String format = null; // 格式
                    if (!text.contains(":")) format = "yyyy-MM-dd";
                    else {// 时间处理(动态格式)
                        if (text.split(":").length == 2) format = "yyyy-MM-dd HH:mm";
                        else if (text.split(":").length == 3) format = "yyyy-MM-dd HH:mm:ss";
                    }
                    assert format != null;
                    setValue(new SimpleDateFormat(format).parse(text));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    public ReturnData handleException(Exception ex, HttpServletRequest request) {
        String msg;
        int code = FAIL_CODE;
        if (ex instanceof BusinessException) {
            BusinessException businessException = (BusinessException) ex;
            msg = businessException.getMessage();
            code = businessException.getCode();
        } else {
            msg = ex.getMessage() == null ? "错误" : ex.getMessage();
            String[] args = msg.split("\r\n");
            if (args.length > 1) {
                msg = args[0];
                int index = msg.indexOf("Exception:");
                if (index != -1) {
                    msg = msg.substring(index + 10);
                }
            }
            if (ex instanceof RuntimeException && Objects.requireNonNull(ex.getMessage()).contains("BusinessException")) {
                logger.error("------------【业务错误：" + msg + "】------------");
            } else {
                if (logger.isInfoEnabled()) {
                    logger.error("×××××××××××××【警告：服务器发生严重错误,请立即处理】×××××××××××××");
                    logger.error("×××××××××××××【异常信息：" + ex.getMessage() + "】×××××××××××××");
                    ex.printStackTrace();
                }
            }
        }
        return jsonView(code, msg);
    }

    /**
     * 错误返回
     */
    protected <T> ReturnData<T> jsonErrView(String message) {
        return jsonView(FAIL_CODE, false, message, null, true, null);
    }

    /**
     * 成功返回
     */
    protected <T> ReturnData<T> jsonSuccessView() {
        return jsonView(FAIL_CODE, false, "返回成功", null, true, null);
    }

    /**
     * 无数据标准返回
     */
    protected <T> ReturnData<T> jsonView(boolean success, String message) {
        return jsonView(success ? SUCCESS_CODE : FAIL_CODE, success, message, null, true, null);
    }

    /**
     * 含数据标准返回
     */
    protected <T> ReturnData<T> jsonView(boolean success, String msg, T data) {
        return jsonView(success ? SUCCESS_CODE : FAIL_CODE, success, msg, data, true, null);
    }

    /**
     * 无数据含返回码
     */
    protected <T> ReturnData<T> jsonView(int code, String msg) {
        return jsonView(code, code == SUCCESS_CODE, msg, null, true, null);
    }

    /**
     * 含数据含返回码 移动端
     */
    protected <T> ReturnData<T> jsonView(int code, boolean success, String msg, T data) {
        return jsonView(code, success, msg, data, true, null);
    }

    /**
     * 含数据含返回码 后台
     */
    protected <T> ReturnData<T> jsonView(int code, String msg, T data) {
        return jsonView(code, code == SUCCESS_CODE, msg, data, true, null);
    }

    /**
     * 含数据不含返回码 （不）加密
     */
    protected <T> ReturnData<T> jsonView(boolean success, String msg, T data, boolean isEncrypt) {
        return jsonView(success ? SUCCESS_CODE : FAIL_CODE, success, msg, data, isEncrypt, null);
    }

    /**
     * 含数据 含TOKEN
     */
    protected <T> ReturnData<T> jsonView(boolean success, String msg, T data, String token) {
        return jsonView(success ? SUCCESS_CODE : FAIL_CODE, success, msg, data, true, token);
    }

    /**
     * APP全参数返回
     */
    protected <T> ReturnData<T> jsonView(int code, boolean success, String msg, T data, boolean isEncrypt, String token) {
        ReturnData<T> returnData = new ReturnData<>();
        returnData.setCode(code);
        returnData.setMsg(msg);
        returnData.setSuccess(success);
        returnData.setIsEncrypt(false);
        returnData.setToken(token);
        returnData.setData(data);
        return returnData;
    }

}
